/* @(#)NodeFragAuditBlock.java
** 
** Copyright (C) 2012 by Steven D. Stamps
**
**             Trademarks & Copyrights
** Flywheel Management Science(TM), Flywheel Management Model(TM),
** Flywheel Story Editor(TM) and FlywheelMS(TM) are exclusive trademarks
** of Steven D. Stamps and may only be used freely for the purpose of
** identifying the unforked version of this software.  Subsequent forks
** may not use these trademarks.  All other rights are reserved.
**
** DecKanGL (Decorated Kanban Glyph Language) and TribKn (Tribal Knowledge)
** are also exclusive trademarks of Steven D. Stamps.  These may be used
** freely within the unforked FlywheelMS application and documentation.
** All other rights are reserved.
**
** gConGUI (game Controller Graphical User Interface) is an exclusive
** trademark of Steven D. Stamps.  This trademark may be used freely
** within the unforked FlywheelMS application and documentation.
** All other rights are reserved.
**
** Trademark information is available at
** <http://www.flywheelms.com/trademarks>
**
** Flywheel Management Science(TM) is a copyrighted body of management
** metaphors, governance processes, and leadership techniques that is
** owned by Steven D. Stamps.  These copyrighted materials may be freely
** used, without alteration, by the community (users and developers)
** surrounding this GPL3-licensed software.  Additional copyright
** information is available at <http://www.flywheelms.org/copyrights>
**
**              GPL3 Software License
** This program is free software: you can use it, redistribute it and/or
** modify it under the terms of the GNU General Public License, version 3,
** as published by the Free Software Foundation. This program is distributed
** in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
** even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
** PURPOSE.  See the GNU General Public License for more details. You should
** have received a copy of the GNU General Public License, in a file named
** COPYING, along with this program.  If you cannot find your copy, see
** <http://www.gnu.org/licenses/gpl-3.0.html>.
*/

package com.flywheelms.library.fmm.node.impl.nodefrag;

import java.util.Date;

import org.json.JSONException;
import org.json.JSONObject;

import com.flywheelms.library.fca.FlywheelCommunityAuthentication;
import com.flywheelms.library.fmm.enumerator.FmmLockStatus;
import com.flywheelms.library.fmm.helper.FmmDateHelper;
import com.flywheelms.library.fmm.node.NodeId;
import com.flywheelms.library.fmm.node.impl.headline.CommunityMember;
import com.flywheelms.library.fmm.node.interfaces.horizontal.FmmNodeAudit;
import com.flywheelms.library.fmm.serialization.FseDocumentSerialization;
import com.flywheelms.library.fmm.serialization.NodeFragAuditBlockSerialization;
import com.flywheelms.library.fse.model.FseParagraph;
import com.flywheelms.library.util.JsonHelper;

public class NodeFragAuditBlock extends FmmNodeFragImpl implements FmmNodeAudit {

	private NodeId createdBy =  CommunityMember.getNullValue().getNodeId();
	private Date createdTimestamp = new Date();
	private NodeId lastUpdatedBy =  CommunityMember.getNullValue().getNodeId();
	private Date lastUpdatedTimestamp = new Date();
	private NodeId lockedBy = CommunityMember.getNullValue().getNodeId(); 
	private Date lockedTimestamp = FmmDateHelper.NULL_DATE;
	private boolean locked = false;
	private int transactionCount = 0;

	public NodeFragAuditBlock(String aParentNodeIdString) {
		super(NodeFragAuditBlock.class, aParentNodeIdString);
	}

	// rehydrate
	public NodeFragAuditBlock(JSONObject aJsonObject) {
		super(
				NodeId.rehydrate(NodeFragAuditBlock.class, JsonHelper.getString(aJsonObject, NodeFragAuditBlockSerialization.key__AUDIT__NODE_ID)),
				JsonHelper.getString(aJsonObject, NodeFragAuditBlockSerialization.key__AUDIT__PARENT_NODE_ID) );
		try {
			setCreatedBy(aJsonObject.getString(NodeFragAuditBlockSerialization.key__AUDIT__CREATED_BY));
			setCreatedTimestamp(JsonHelper.getDate(aJsonObject, NodeFragAuditBlockSerialization.key__AUDIT__CREATED_TIMESTAMP));
			setLastUpdatedBy(aJsonObject.getString(NodeFragAuditBlockSerialization.key__AUDIT__LAST_UPDATED_BY));
			setLastUpdatedTimestamp(JsonHelper.getDate(aJsonObject, NodeFragAuditBlockSerialization.key__AUDIT__LAST_UPDATED_TIMESTAMP));
			setLocked(aJsonObject.getBoolean(NodeFragAuditBlockSerialization.key__AUDIT__LOCKED));
			setLockedBy(aJsonObject.getString(NodeFragAuditBlockSerialization.key__AUDIT__LOCKED_BY));
			setLockedTimestamp(JsonHelper.getDate(aJsonObject, NodeFragAuditBlockSerialization.key__AUDIT__LOCKED_TIMESTAMP));
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public NodeId getLastUpdatedBy() {
		return this.lastUpdatedBy;
	}

	@Override
	public void setLastUpdatedBy(NodeId aNodeId) {
		this.lastUpdatedBy = aNodeId;
	}

	@Override
	public void setLastUpdatedBy(String aNodeIdString) {
		this.lastUpdatedBy.setNodeIdString(aNodeIdString);
	}

	@Override
	public Date getLastUpdatedTimestamp() {
		return this.lastUpdatedTimestamp;
	}

	@Override
	public void setLastUpdatedTimestamp(Date aTimestamp) {
		this.lastUpdatedTimestamp = aTimestamp;
	}

	@Override
	public NodeId getCreatedBy() {
		return this.createdBy;
	}

	@Override
	public void setCreatedBy(NodeId aNodeIdString) {
		this.createdBy = aNodeIdString;
	}

	@Override
	public void setCreatedBy(String aNodeIdString) {
		this.createdBy.setNodeIdString(aNodeIdString);
	}

	@Override
	public Date getCreatedTimestamp() {
		return this.createdTimestamp;
	}

	@Override
	public void setCreatedTimestamp(Date aTimestamp) {
		this.createdTimestamp = aTimestamp;
	}

	@Override
	public NodeId getLockedBy() {
		return this.lockedBy;
	}

	@Override
	public void setLockedBy(NodeId aNodeId) {
		this.lockedBy = aNodeId;
	}

	@Override
	public void setLockedBy(String aNodeIdString) {
		this.lockedBy.setNodeIdString(aNodeIdString);
	}

	@Override
	public Date getLockedTimestamp() {
		return this.lockedTimestamp;
	}

	@Override
	public void setLockedTimestamp(Date aTimestamp) {
		this.lockedTimestamp = aTimestamp;
	}

	@Override
	public boolean isLocked() {
		return this.locked;
	}
	
	public int getTransactionCount() {
		return this.transactionCount;
	}

	public void setTransactionCount(int aTransactionCount) {
		this.transactionCount = aTransactionCount;
	}

	public int getUpdatedTransactionCount() {
		++this.transactionCount;
		return this.transactionCount;
	}

	@Override
	public void lock() {
		setLocked(true);
		setLockedBy(FlywheelCommunityAuthentication.getInstance().getFcaUserCredentials().getFcaUserId());
		this.setLockedTimestamp(new Date());
	}
	
	@Override
	public void unlock() {
		setLocked(false);
		// we want to know who unlocked it, and when
		setLockedBy(FlywheelCommunityAuthentication.getInstance().getFcaUserCredentials().getFcaUserId());
		this.setLockedTimestamp(new Date());
	}

	@Override
	public void setLocked(boolean isLocked) {
		this.locked = isLocked;
	}

	@Override
	public NodeFragAuditBlock getAuditBlock() {
		return this;
	}

	@Override
	public void setAuditBlock(NodeFragAuditBlock auditBlock) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public String getCreatedByNodeIdString() {
		return this.createdBy.getNodeIdString();
	}

	@Override
	public String getLastUpdatedByNodeIdString() {
		return this.lastUpdatedBy.getNodeIdString();
	}

	@Override
	public String getLockedByNodeIdString() {
		return this.lockedBy.getNodeIdString();
	}

	public static NodeFragAuditBlock createNewAuditBlock(String aDocumentId) {
		NodeFragAuditBlock theAuditBlock = new NodeFragAuditBlock(aDocumentId);
		theAuditBlock.setCreatedTimestamp(new Date());
		theAuditBlock.setCreatedBy(FlywheelCommunityAuthentication.getInstance().getFcaUserCredentials().getFcaUserId());
		theAuditBlock.setLastUpdatedTimestamp(new Date());
		theAuditBlock.setLastUpdatedBy(FlywheelCommunityAuthentication.getInstance().getFcaUserCredentials().getFcaUserId());
		theAuditBlock.setLocked(false);
		theAuditBlock.setLockedTimestamp(FmmDateHelper.NULL_DATE);
		theAuditBlock.setLockedBy(FlywheelCommunityAuthentication.getInstance().getFcaUserCredentials().getFcaUserId());
		return theAuditBlock;
	}

	public boolean isUnlocked() {
		return ! isLocked();
	}

	@Override
	public FmmLockStatus getLockStatus() {
		if(this.locked) {
			return FmmLockStatus.LOCKED;
		}
		if(! this.locked && this.lockedBy == CommunityMember.getNullValue().getNodeId()) {
			return FmmLockStatus.NEVER_LOCKED;
		}
		return FmmLockStatus.UNLOCKED;
	}
	
	public JSONObject getJsonObject() {
		JSONObject theJsonObject = new JSONObject();
		try {
			theJsonObject.put(NodeFragAuditBlockSerialization.key__AUDIT__NODE_ID, getNodeId().getNodeIdString());
			theJsonObject.put(NodeFragAuditBlockSerialization.key__AUDIT__PARENT_NODE_ID, getParentNodeIdString());
			theJsonObject.put(NodeFragAuditBlockSerialization.key__AUDIT__CREATED_BY, getCreatedBy().getNodeIdString());
			JsonHelper.putDate(theJsonObject, NodeFragAuditBlockSerialization.key__AUDIT__CREATED_TIMESTAMP, getCreatedTimestamp());
			theJsonObject.put(NodeFragAuditBlockSerialization.key__AUDIT__LAST_UPDATED_BY, getLastUpdatedBy().getNodeIdString());
			JsonHelper.putDate(theJsonObject, NodeFragAuditBlockSerialization.key__AUDIT__LAST_UPDATED_TIMESTAMP, getLastUpdatedTimestamp());
			theJsonObject.put(NodeFragAuditBlockSerialization.key__AUDIT__LOCKED, isLocked());
			theJsonObject.put(NodeFragAuditBlockSerialization.key__AUDIT__LOCKED_BY, getLockedBy().getNodeIdString());
			JsonHelper.putDate(theJsonObject, NodeFragAuditBlockSerialization.key__AUDIT__LOCKED_TIMESTAMP, getLockedTimestamp());
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return theJsonObject;
	}
	
	public String getSerialized() {
		return getJsonObject().toString();
	}
	
	public NodeFragAuditBlock getClone() {
		return new NodeFragAuditBlock(getJsonObject());
	}

}
